#ifndef _CDAYVIEW_H_
#define _CDAYVIEW_H_

#include "auto.h"

#include "ccalendarevent.h"

#include <buola/datetime/cdatetime.h>
#include <buola/utility/usignal.h>
#include <buola/widgets/cwidget.h>

namespace buola { namespace bcal {

class CDayView : public gui::CWidget
{
public:
    struct SEntry
    {
        CCalendarEvent *mEvent;

        int mSlot;
        int mNumSlots;

        CRect_d mRect;

        img::CColor mLineColor;
        img::CColor mFillColor;

        bool mCreating;
        bool mMoving;
    };

    struct SDay
    {
        double mXL,mXR;
        std::vector<std::unique_ptr<SEntry>> mEntries;
    };

    enum EValid
    {
        VALID_NONE=0,
        VALID_ENTRIES=(1<<0),
        VALID_SLOTS=(1<<1),
        VALID_SHAPE=(1<<2),
        VALID_POSITIONS=(1<<3)
    };

    DECLARE_FRIEND_ENUM_BITOPS(EValid)

    CDayView(CCalManager *pManager,int pNDays=1,int pFirstDay=CDate::MONDAY);
    ~CDayView();

//Managing fields
    void SetDate(const CDate &pDate);
    void SetToday();

    void Next();
    void Previous();

private:
    void Invalidate(EValid pWhat)   {   mValid&=~pWhat; }

    void CalcEntries();
    void CalcSlots();
    void CalcShape();
    void CalcPositions();

    void MakeValid(EValid pWhat);

    SEntry *GetEntryAt(const CPoint_d &pP);
    CDateTime GetDateTimeAt(const CPoint_d &pP);

public:
////////////// Event handling //////////////
    virtual void OnPreExpose();
    virtual void OnExpose(const gui::CExposeEvent &pE);
    virtual void OnButtonDown(const gui::CMouseEvent &pE);
    virtual void OnButtonUp(const gui::CMouseEvent &pE);
    virtual void OnMouseMove(const gui::CMouseEvent &pE);
    virtual void OnMouseWheel(const gui::CMouseEvent &pE);
    virtual void OnSize(const gui::CGeometryEvent &pE);

    virtual void OnStyleChanged(TStyle);

    void OnScroll(int pPos);

    void OnCalendarAdded(CCalendar *pCalendar);
    void OnCalendarRemoved(CCalendar *pCalendar);

protected:
/////////////// protected functions //////////////

public:
    USignal<void(const std::wstring&)> sChangeTitle;

private:
    img::PFont mFont;
    img::PFont mSmallFont;

    CDate mDate;
    CDate mFirstDate;

    CCalManager *mManager;

    int mRows;
    double mRowHeight;

    CRect_d mHoursRect;

    EValid mValid;

    gui::PScrollBar mScrollBar;

    std::vector<std::unique_ptr<SDay>> mDays;

    int mNDays;
    int mFirstDay;

    struct
    {
        bool mActive;
        CDateTime mStart;
        CDateTime mEnd;
        CCalendarEvent *mEvent;
    } mCreating;

    struct
    {
        bool mActive;
        CDateTime mStart;
        CPoint_d mAnchor;
        CPoint_d mPoint;
        CCalendarEvent *mEvent;
        int mSlot;
        int mNumSlots;
    } mMoving;

    CPoint_d mScrollPos;
};

inline bool operator<(const CDayView::SEntry &p1,const CDayView::SEntry &p2)
{
    if(p1.mMoving||p1.mCreating) return false;
    if(p2.mMoving||p2.mCreating) return true;
    return p1.mEvent->GetStart()<p2.mEvent->GetStart()||
        (p1.mEvent->GetStart()==p2.mEvent->GetStart()&&
            p1.mEvent->GetEnd()<p2.mEvent->GetEnd());
}

/*namespace buola*/ } /*namespace bcal*/ }

#endif
